const CONFIG = require('../config/')
const util = require('util')
const request = require('superagent')
const fs = require('fs')
const path = require('path')

const accessFile = util.promisify(fs.access)
const writeFile = util.promisify(fs.writeFile)

const tokenPath = path.resolve(__dirname, './wechat-access-token.json')

class Wechat{
    constructor(){
        Object.keys(CONFIG).forEach(k => {
            this[k] = CONFIG[k]
        })
    }

    async sendTemplate(params){
        const { templateId, openId, url, data } = params
        try {
            const accessToken = await this.getAccessToken()
            const requestUrl = util.format(
                this.apiURL.templateApi,
                this.apiDomain,
                accessToken
            )
            const params = {
                touser: openId,
                template_id: templateId,
                url,
                data
            }
            const { body } = await request
                .post(requestUrl)
                .set('Content-Type', 'application/json')
                .send(JSON.stringify(params))
            return body            
        } catch (error) {
            throw error
        }
    }

    async sendKfMessage(openId, content){
        try {
            const accessToken = await this.getAccessToken()
            const url = util.format(
                this.apiURL.kfMessageApi,
                this.apiDomain,
                accessToken
            )
            const params = {
                touser: openId,
                msgtype: "text",
                text: {
                    content:content
                }
            }
            const { body } = await request
                .post(url)
                .set('Content-Type', 'application/json')
                .send(JSON.stringify(params))
            return body
        } catch (error) {
            throw error
        }
    }

    async getUserInfo(openId){
        try {
            const accessToken = await this.getAccessToken()
            const url = util.format(
                this.apiURL.userInfoApi,
                this.apiDomain,
                accessToken,
                openId
            )     
            const { body } = await request.get(url)
            return body
        } catch (error) {
            throw error
        }
    }

    async getAccessToken(){
        const tokenFile = await this.getFile()
        if(tokenFile.hasOwnProperty('access_token') && tokenFile.expires_time > Date.now()){
            return tokenFile.access_token
        }
        const result = await this.requestForAccessToken()
        if(result.hasOwnProperty('errcode')){
            throw result
        }
        result.expires_time = Date.now() + (parseInt(result.expires_in) - 200) * 1000
        return await this.saveToken(result)
    }

    async requestForAccessToken(){
        const url = util.format(
            this.apiURL.accessTokenApi, 
            this.apiDomain, 
            this.appId, 
            this.appSecret
        )
        const { body } = await request.get(url)
        return body
    }

    async saveToken(result){
        try {
            await writeFile(tokenPath, JSON.stringify(result))
            return result
        } catch (error) {
            console.log(error)            
        }
    }

    async getFile(){
        try {
            const result = await accessFile(tokenPath, fs.F_OK)
            return require(tokenPath)
        } catch (error) {
            const result = {}
            await writeFile(tokenPath, JSON.stringify(result))
            return result
        }
    }
}

module.exports = exports = Wechat